package com.pwc.conversionTool.config;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * dependency dom4j lib and appache common io basic function for reading xml
 */
public class ConfigBase {

	private Document document = null;

	private File xmlFile = null;

	/**
	 * the util of
	 * 
	 * @param sevlet
	 * @throws DocumentException
	 */
	public ConfigBase(String path) throws DocumentException {
		super();
		xmlFile = new File(path);
		SAXReader saxReader = new SAXReader();
		document = saxReader.read(xmlFile);
	}

	/**
	 * give a empty constructor
	 */
	public ConfigBase() {

	}

	/**
	 * save document to file which is sent before
	 * 
	 * @throws IOException
	 */
	public void saveDocument() throws IOException {
		XMLWriter writer = new XMLWriter(new FileWriter(xmlFile));
		writer.write(document);
		writer.close();
	}

	/**
	 * read xml to document
	 * 
	 * @param xml
	 * @throws DocumentException
	 */
	public void readStringToXML(String xml) throws DocumentException {
		SAXReader reader = new SAXReader();
		document = reader.read(new StringReader(xml));
	}

	/**
	 * read the string xml and save it to file
	 * 
	 * @param xml
	 * @throws DocumentException
	 * @throws IOException
	 */
	public void saveDocument(String xml) throws DocumentException, IOException {
		readStringToXML(xml);
		saveDocument();
	}

	/**
	 * get single file by xpath
	 * 
	 * @param xPath
	 * @return
	 */
	public String getSingleStringValue(String xPath) {
		String result = null;
		Node node = document.selectSingleNode(xPath);
		if(node!=null)
		result = node.getStringValue();
		return result;
	}

	/**
	 * set single node using xpath
	 * 
	 * @param xPath
	 * @param value
	 */
	public void setSingleStringValue(String xPath, String value) {
		Node node = document.selectSingleNode(xPath);
		node.setText(value);
	}

	/**
	 * add node 
	 * @param xPath location of the node	
	 * @param nodeName
	 * @param value
	 */
	public void addNodeByXpath(String xPath, String nodeName, String value) {
		Element root = (Element) document.selectSingleNode(xPath);
		Element temp = root.addElement(nodeName);
		temp.setText(value);
	}

	/**
	 * delete node by xPath
	 * @param xPath
	 * @param value
	 */
	public void deleteNodeByXpath(String xPath) {
		List<Element> data = document.selectNodes(xPath);
		for (Element element : data) {
			element.detach();
		}		
	}

	/**
	 * get list of file by xPath
	 * 
	 * @param xPath
	 * @return
	 */
	public List<String> getStringArray(String xPath) {
		List<String> list = new ArrayList<String>();
		List<Element> composites = document.selectNodes(xPath);
		if (composites != null) {
			for (Element e : composites) {
				list.add(e.getStringValue());
			}
		}
		return list;
	}

	/**
	 * get childe key and value from a path
	 * 
	 * @param xPath
	 * @return
	 */
	public Map<String, String> getXMLMap(String xPath) {
		Map<String, String> hashMap = new HashMap<String, String>();
		Element data = (Element) document.selectSingleNode(xPath);
		List<Node> composites = data.elements();
		if (composites != null) {
			for (Node e : composites) {
				hashMap.put(e.getName(), e.getText());
			}
		}
		return hashMap;
	}

	/**
	 * overrided to string function
	 */
	public String toString() {
		return document.asXML();
	}

	/**
	 * get the String of config file
	 * 
	 * @return
	 * @throws IOException
	 */
	public String getStringFromFile() throws IOException {

		String result = FileUtils.readFileToString(xmlFile);

		return result;
	}

	/**
	 * save file
	 * 
	 * @param xmlConfig
	 * @return
	 * @throws IOException
	 */
	public void saveFile(String xmlConfig) throws IOException {

		FileUtils.writeStringToFile(xmlFile, xmlConfig);

	}

	/**
	 * getter
	 * 
	 * @return
	 */
	public File getXmlFile() {
		return xmlFile;
	}

	/**
	 * setter
	 * 
	 * @param xmlFile
	 */
	public void setXmlFile(File xmlFile) {
		this.xmlFile = xmlFile;
	}

}
